package com.qiyi.player.core.video.provider.actors.providertile
{
   import flash.events.EventDispatcher;
   import com.qiyi.player.core.IDestroy;
   import com.qiyi.player.core.model.impls.Segment;
   import com.qiyi.player.core.video.file.actors.datatile.IFlvBlock;
   import com.qiyi.player.core.player.coreplayer.ICorePlayer;
   import flash.net.URLStream;
   import flash.utils.Timer;
   import com.qiyi.player.base.logging.ILogger;
   import com.qiyi.player.base.pub.EnumItem;
   import flash.events.Event;
   import flash.events.HTTPStatusEvent;
   import flash.events.ProgressEvent;
   import flash.events.IOErrorEvent;
   import flash.events.SecurityErrorEvent;
   import flash.events.TimerEvent;
   import flash.utils.getTimer;
   import flash.net.URLRequest;
   import com.qiyi.player.core.video.events.ProviderEvent;
   import com.qiyi.player.core.video.def.ProviderTileTypeEnum;
   import com.qiyi.player.base.logging.Log;
   
   public class HttpProvider extends EventDispatcher implements IDestroy
   {
      
      public function HttpProvider(param1:IFlvBlock, param2:ICorePlayer, param3:int) {
         this._log = Log.getLogger("com.qiyi.player.core.video.provider.coreprovider.parts.HttpProvider");
         super();
         this._block = param1;
         this._segment = param1.segment;
         this._holder = param2;
         this._timeout = param3;
      }
      
      protected var _segment:Segment;
      
      protected var _url:String;
      
      protected var _bytesLoaded:Number;
      
      protected var _bytesTotal:Number = 0;
      
      protected var _currentRetry:Number = 0;
      
      protected var _block:IFlvBlock;
      
      protected var _holder:ICorePlayer;
      
      protected var _timeout:int;
      
      protected var _errno:int;
      
      private var _isOpen:Boolean = false;
      
      private var _status:int = 0;
      
      private var _isComplete:Boolean = false;
      
      private var _urlstream:URLStream;
      
      private var _downloadBeginDate:int = 0;
      
      private var _downloadEndDate:int = 0;
      
      private var _downloadDuration:Number = 0;
      
      private var _monitor:Timer;
      
      private var _lastRecordTime:int = 0;
      
      private var _lastTime:int = 0;
      
      private var _lastLoaded:int = 0;
      
      protected var _log:ILogger;
      
      public function get block() : IFlvBlock {
         return this._block;
      }
      
      public function get url() : String {
         return this._url;
      }
      
      public function get isOpen() : Boolean {
         return this._isOpen;
      }
      
      public function get loadComplete() : Boolean {
         return this._isComplete;
      }
      
      public function get status() : int {
         return this._status;
      }
      
      public function get type() : EnumItem {
         return null;
      }
      
      public function get segment() : Segment {
         return this._segment;
      }
      
      public function load(param1:int) : Boolean {
         this._currentRetry = 0;
         return true;
      }
      
      public function destroy() : void {
         this.close();
         this._block = null;
         this._segment = null;
         this._holder = null;
      }
      
      public function close() : void {
         if(this._urlstream == null)
         {
            return;
         }
         this._isOpen = false;
         this._isComplete = false;
         var _loc1_:* = false;
         if(this._urlstream.connected)
         {
            this._log.info("closing :" + this._url);
            this._urlstream.close();
            _loc1_ = true;
         }
         this.destroyStream();
      }
      
      protected function createStream() : void {
         this._urlstream = new URLStream();
         this._urlstream.addEventListener(Event.OPEN,this.onOpen);
         this._urlstream.addEventListener(HTTPStatusEvent.HTTP_STATUS,this.onStatus);
         this._urlstream.addEventListener(Event.COMPLETE,this.onComplete);
         this._urlstream.addEventListener(ProgressEvent.PROGRESS,this.onProgress);
         this._urlstream.addEventListener(IOErrorEvent.IO_ERROR,this.onIOError);
         this._urlstream.addEventListener(SecurityErrorEvent.SECURITY_ERROR,this.onSecurityError);
         this._monitor = new Timer(1000);
         this._monitor.addEventListener(TimerEvent.TIMER,this.onMonitorTimer);
         this._monitor.start();
         this._lastRecordTime = getTimer();
      }
      
      protected function destroyStream() : void {
         if(this._urlstream == null)
         {
            return;
         }
         this._isOpen = false;
         this._block.endAppend();
         if(this._monitor)
         {
            this._monitor.stop();
            this._monitor.removeEventListener(TimerEvent.TIMER,this.onMonitorTimer);
            this._monitor = null;
         }
         if(this._urlstream.connected)
         {
            this._urlstream.close();
         }
         this._urlstream.removeEventListener(Event.OPEN,this.onOpen);
         this._urlstream.removeEventListener(HTTPStatusEvent.HTTP_STATUS,this.onStatus);
         this._urlstream.removeEventListener(Event.COMPLETE,this.onComplete);
         this._urlstream.removeEventListener(ProgressEvent.PROGRESS,this.onProgress);
         this._urlstream.removeEventListener(IOErrorEvent.IO_ERROR,this.onIOError);
         this._urlstream.removeEventListener(SecurityErrorEvent.SECURITY_ERROR,this.onSecurityError);
         this._urlstream = null;
      }
      
      public function stopAndReload() : void {
      }
      
      protected function startLoad() : void {
         if(this._urlstream != null)
         {
            this.close();
         }
         if(this._url == null || this._url == "")
         {
            throw new ArgumentError("Null request in HTTPProviderDownloader open method.");
         }
         else
         {
            req = new URLRequest(this._url);
            this._isComplete = false;
            this._isOpen = false;
            this.createStream();
            this._log.info("Loading (retry=" + this._currentRetry + "):" + this._url);
            this._downloadBeginDate = getTimer();
            this._lastTime = 0;
            this._bytesLoaded = 0;
            this._bytesTotal = 0;
            this._block.complete = false;
            try
            {
               this._urlstream.load(req);
            }
            catch(e:SecurityError)
            {
               _log.info("catched error: " + e.message);
               onSecurityError(null);
            }
            catch(e:Error)
            {
               _log.info("catched error: " + e.message);
               onIOError(null);
            }
            return;
         }
      }
      
      protected function onOpen(param1:Event) : void {
         this._block.startAppend();
         this._holder.runtimeData.useDataModel = true;
         this._isOpen = true;
         this._log.info("urlstream is open");
         dispatchEvent(new ProviderEvent(ProviderEvent.Evt_Connected));
      }
      
      protected function onStatus(param1:HTTPStatusEvent) : void {
         this._status = param1.status;
         this._log.info("get http response status: " + param1.status);
      }
      
      protected function onComplete(param1:Event) : void {
         if(this._isComplete)
         {
            return;
         }
         this._holder.runtimeData.currentSpeed = 0;
         this._downloadEndDate = getTimer();
         this._downloadDuration = this._downloadEndDate - this._downloadBeginDate;
         if(this.type == ProviderTileTypeEnum.INTERNET)
         {
            this._holder.runtimeData.preAverageSpeed = int(this._bytesLoaded * 1000 / this._downloadDuration);
         }
         this._isComplete = true;
         this._log.info("Loading complete. It took " + this._downloadDuration + " milliseconds and " + this._currentRetry + " retries to download " + this._bytesLoaded + " bytes.");
         this.destroyStream();
         dispatchEvent(new ProviderEvent(ProviderEvent.Evt_LoadComplete,this._bytesLoaded - this._bytesTotal >= 0));
      }
      
      protected function onProgress(param1:ProgressEvent) : void {
         if(this._status > 399)
         {
            return;
         }
         if(this._block == null)
         {
            return;
         }
         this._lastRecordTime = getTimer();
         if(this._bytesTotal == 0)
         {
            this._log.info("received first package: " + param1.bytesLoaded + ", total bytes: " + param1.bytesTotal);
            this._bytesTotal = param1.bytesTotal;
            this._lastTime = getTimer();
            this._lastLoaded = param1.bytesLoaded;
         }
         var _loc2_:int = getTimer();
         if(this.type == ProviderTileTypeEnum.INTERNET)
         {
            if(_loc2_ - this._lastTime > 1000)
            {
               this._holder.pingBack.addCDNStatistics(param1.bytesLoaded - this._lastLoaded);
               this._holder.runtimeData.currentSpeed = (param1.bytesLoaded - this._lastLoaded) * 1000 / (_loc2_ - this._lastTime);
               this._holder.runtimeData.currentAverageSpeed = param1.bytesLoaded * 1000 / (_loc2_ - this._downloadBeginDate);
               this._lastTime = _loc2_;
               this._lastLoaded = param1.bytesLoaded;
            }
         }
         this._bytesLoaded = param1.bytesLoaded;
         if(!this._block.appendBytes(this._urlstream))
         {
            this.onDataError();
            return;
         }
         if(this._bytesLoaded - this._bytesTotal >= 0)
         {
            this._block.complete = true;
         }
         if(this._block.complete)
         {
            this._log.info("parsing complete! current bytes: " + param1.bytesLoaded);
            this.onComplete(null);
         }
      }
      
      protected function onDataError() : void {
         this._errno = 4016;
         this.retry();
      }
      
      protected function onIOError(param1:Event) : void {
         this._holder.runtimeData.currentSpeed = 0;
         this._downloadEndDate = getTimer();
         this._downloadDuration = this._downloadEndDate - this._downloadBeginDate;
         this._isComplete = false;
         this._errno = 4012;
         this._log.warn("Loading failed. It took " + this._downloadDuration + " milliseconds and " + this._currentRetry + " retries to fail while downloading [" + this._url + "].");
         this.retry();
      }
      
      protected function onSecurityError(param1:SecurityErrorEvent) : void {
         this._log.error("URLStream SecurityError");
         this._holder.runtimeData.currentSpeed = 0;
         this._holder.runtimeData.useDataModel = false;
         this._isComplete = false;
         this._errno = 4017;
         this.retry();
      }
      
      private function onMonitorTimer(param1:TimerEvent) : void {
         var _loc2_:int = getTimer();
         if(_loc2_ - this._lastRecordTime < this._timeout)
         {
            return;
         }
         if(!this._isOpen)
         {
            this._log.warn("timeout for open socket,errno=4011");
            this._errno = 4011;
            this.retry();
         }
         else
         {
            this._log.warn("timeout for loading, errno=4014, loaded bytes: " + this._bytesLoaded + "/" + this._bytesTotal);
            this._errno = 4014;
            this.retry();
         }
      }
      
      protected function retry() : void {
         this._log.info("retry....., retryCount: " + this._currentRetry);
      }
   }
}
